<?php
	abstract class IMDB_Search {
		
		const REGEX_SEARCH_ROW = '#<tr>(.*?)</tr>#i';
		const REGEX_SEARCH_IMG = '#<td(?:.*?)valign="top">(?:.*?)<img src="(.*?)"(?:.*?)>(?:.*?)</td>#i';
		const REGEX_SEARCH_DATA = '#<td valign="top"(?:.*?)(?:class="charcell")?>(?:<img src="(?:http://i.media-imdb.com)?/images/b.gif" width="1" height="6"><br>)?<a(?:.*?)href="(/(.*?)/(.*?)/)"(?:.*?)>(.*?)</a>(.*?)(\((?:.*?)\))(?:\s*?)??(?:((?:</?small>|<br>)(?:.*?))?)</td>#i';
		
		protected $sQuery;
		protected $sSearchURL;
		protected $iType;
		protected $sSearchType;
		protected $sSearchDisplay;
		protected $aSearchResults;
		
		public function __construct($sQuery, $iType) {
			$this->sQuery = $sQuery;
			$this->iType = $iType;
			$this->sSearchType = IMDB::$ENUM_SEARCH_TYPE[$this->iType][0];
			$this->sSearchDisplay = IMDB::$ENUM_SEARCH_TYPE[$this->iType][1];
			$this->sSearchURL = sprintf(IMDB::URL_SEARCH, $this->sSearchType, urlencode($this->sQuery));
			$this->start();
		}
		private function start() {
			$sRawContent = file_get_contents($this->sSearchURL);
			$sRawContent = $this->preParse($sRawContent);
			$this->parse($sRawContent);
		}
		private function preParse($sInput) {
			$Start = '<div id="main">';
			$Start = stripos($sInput, $Start);
			$sInput = substr($sInput, $Start);
			
			$End = '<script type="text/javascript">';
			$End = stripos($sInput, $End);
			$sInput = substr($sInput, 0, $End);
			
			return $sInput;
		}
		
		private function parse($sInput) {
			$Results = array();
			foreach (IMDB::$ENUM_RESULT as $iType => $sType) {
				$Results[$iType] = array();
				
				$sType = sprintf($sType, $this->sSearchDisplay);
				$iFind = stripos($sInput, $sType);
				if ($iFind === false)
					continue;
				
				$iStart = stripos($sInput, "<table>", $iFind);
				if ($iStart === false)
					continue;
				$iEnd = stripos($sInput, "</table>", $iStart);
				
				$sBlock = substr($sInput, $iStart, $iEnd-$iStart);
				
				//Parse out each table row in the table
				$aRows = array();
				preg_match_all(self::REGEX_SEARCH_ROW, $sBlock, $aRows);
				$aRows = $aRows[1];
				
				//Loop over rows and parse each
				foreach ($aRows as $sRow) {
					$sImage = "";
					$sID = "";
					$sLink = "";
					$sLinkText = "";
					$sBeforeBracket = "";
					$sBracket = "";
					$sAfterBracket = "";
					
					//Parse out image, if there is one...
					$aImage = array();
					preg_match(self::REGEX_SEARCH_IMG, $sRow, $aImage);
					$sImage = $aImage[1];
					if (!stripos($sImage, "images/b.gif") && !empty($sImage)) {
						$aReplace = array("SY30", "SX23");
						$aWith = array("SY%s", "SX%s");
						$sImage = str_replace($aReplace, $aWith, $sImage);
						$sImage = $sImage;
					} else
						$sImage = false;
					
					//Cut out the last table data to prevent the last regex from exploding..
					$sFind = '#<td valign="top" class="charcell">#i';
					$aIndex = array();
					$bRes = (bool) preg_match($sFind, $sRow, $aIndex);
					if ($bRes)
						continue;
					$iIndex = strripos($sRow, "<td valign=\"top\">");
					$sRow = substr($sRow, $iIndex);
					
					//Parse out the rest of the search information provided, this is only a rough parse
					//it is expected that this is refined in the classes which extend this
					$aData = array();
					preg_match(self::REGEX_SEARCH_DATA, $sRow, $aData);
					foreach ($aData as $K => $V) {
						$aData[$K] = str_replace("&#x27;", "'", $V);
					}
					$sLink = trim(html_entity_decode($aData[1]));
					$sID = trim(html_entity_decode($aData[3]));
					$sLinkText = trim(html_entity_decode($aData[4]));
					$sBeforeBracket = trim(html_entity_decode($aData[5]));
					$sBracket = trim(html_entity_decode($aData[6]));
					$sAfterBracket = "";
					if (isset($aData[7]))
						$sAfterBracket = trim(html_entity_decode($aData[7]));
					
					//Done parsing this row, put it in memory
					$oNew = new stdClass;
					$oNew->sID = $sID;
					$oNew->sLink = $sLink;
					$oNew->sLinkText = $sLinkText;
					$oNew->sBeforeBracket = $sBeforeBracket;
					$oNew->sBracket = $sBracket;
					$oNew->sAfterBracket = $sAfterBracket;
					$oNew->sImage = $sImage;
					$oNew->iType = $iType;
					
					$oNew = $this->postParse($oNew);
					
					$Results[$iType][] = $oNew;
				}
			}
			$this->aSearchResults = $Results;
		}
		
		abstract protected function postParse($oResult);
		
		public function getResults($iType = -1) {
			if ($iType == IMDB::RESULT_ALL) {
				$Out = array();
				foreach ($this->aSearchResults as $iType => $aResults) {
					foreach ($aResults as $oResult) {
						$Out[] = $oResult;
					}
				}
				return $Out;
			} else
				return $this->aSearchResults[$iType];
		}
	}
?>